///  <copyright file="MallowMain.cs" company="Infozoom" author="Stefan Zschocke">
///    You must not remove this notice, or any other, from this software.
///    Otherwise do with it whatever you want.
///    infoZoom may not be made liable for any damages whatsoever 
///    (including, without limitation, damages for loss of business profits, 
///    business interruption, loss of business information or other pecuniary loss)
///    arising out of use of or inability to use the Software
/// </copyright>
using System;
using System.Xml;

namespace Mallow
{
    /// <summary>
    /// Summary description for NameGenerator.
    /// </summary>
    internal class NameGenerator
    {
        private string mPrefix;
        private int mNextFree = 0;
        System.Collections.Specialized.NameValueCollection mAllNames = null;
        const int MaxLength = 72;

        internal NameGenerator(XmlNode startNode, XmlNamespaceManager nSpaceMgr, string tagToCheck, string prefix, bool fillAll)
        {
            mPrefix = prefix.ToLower();
            XmlNodeList tags = startNode.SelectNodes("descendant-or-self::" + tagToCheck, nSpaceMgr);
            if (fillAll)
            {
                mAllNames = new System.Collections.Specialized.NameValueCollection();
            }

            foreach (XmlNode node in tags)
            {
                string curName = node.Attributes.GetNamedItem("Id").Value;
                if (fillAll)
                {
                    mAllNames.Set(curName.ToLower(), curName);
                }
                if (curName.ToLower().StartsWith(mPrefix))
                {
                    try
                    {  
                        // if not int then Parse might fail
                        int curValue = int.Parse(curName.Substring(mPrefix.Length));
                        if (curValue >= mNextFree) mNextFree = curValue + 1;
                    }
                    catch { }
                }
            }
        }

        internal string GetNextFreeName()
        {
            return string.Format("{0}{1}", mPrefix, mNextFree++);
        }
        /**
         * Assumes fillAll was set to true in ctor
        */

        internal string MakeCompositeName(string[] parts)
        {
            string composite = "";
            while (true)
            {
                int totalLength = 0;
                composite = "";
                for (int i = 0; i < parts.Length; i++)
                {
                    if (totalLength == 0 && parts[i].Length > 0)
                    {
                        char firstChar = parts[i][0];
                        bool firstCharIsBad = !((firstChar >= 'A' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'z'));
                        if (firstCharIsBad)
                        {
                            totalLength += mPrefix.Length;
                            composite += mPrefix;
                        }
                    }
                    totalLength += parts[i].Length;
                    if (composite.Length > 0 && char.IsLower(parts[i][0]))
                    {
                        composite += parts[i].Substring(0, 1).ToUpper() + parts[i].Substring(1);
                    }
                    else
                    {
                        composite += parts[i];
                    }
                }

                if (totalLength == 0)
                {
                    composite = mPrefix;
                    totalLength = mPrefix.Length;
                }

                if (totalLength <= MaxLength)
                {
                    break;
                }

                double fraction = (double)MaxLength / (double)totalLength;
                for (int i = 0; i < parts.Length; i++)
                {
                    int curLength = (int)Math.Floor((double)parts[i].Length * fraction);
                    if (curLength == 0)
                    {
                        curLength = 1;
                    }
                    if (curLength < parts[i].Length)
                    {
                        parts[i] = parts[i].Substring(0, curLength);
                    }
                }
            }
            for (int i = 0; i < composite.Length; i++)
            {
                char c = composite[i];
                if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9'))
                {
                }
                else
                {
                    composite = composite.Replace(c, '_');
                }
            }

            int nextPostFix = 0;
            string compositeStart = composite;

            while (true)
            {
                string cLower = composite.ToLower();
                if (mAllNames.Get(cLower) != null)
                {
                    string postFix = nextPostFix.ToString();
                    nextPostFix++;
                    int l = MaxLength - compositeStart.Length - postFix.Length;
                    if (l < 0)
                    {
                        composite = compositeStart.Substring(0, compositeStart.Length + l) + postFix;
                    }
                    else
                    {
                        composite = compositeStart + postFix;
                    }
                }
                else
                {
                    mAllNames.Set(cLower, composite);
                    return composite;
                }
            }
        }
    }
}
